using System;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;
using RaisingStudio.SmallBasicCompiler.Completion;

namespace RaisingStudio.SmallBasicCompiler.Statements
{
    public class SubroutineStatement : Statement
    {
        public List<Statement> SubroutineBody = new List<Statement>();
        public TokenInfo SubroutineName;
        public TokenInfo SubToken;
        public TokenInfo EndSubToken;
        public override void AddSymbols(SymbolTable symbolTable)
        {
            if (this.SubroutineName.Token != Token.Illegal)
            {
                symbolTable.AddSubroutine(this.SubroutineName);
            }
            foreach (Statement current in this.SubroutineBody)
            {
                current.AddSymbols(symbolTable);
            }
        }
        public override void PrepareForEmit(CodeGenScope scope)
        {
            MethodBuilder methodBuilder = scope.TypeBuilder.DefineMethod(this.SubroutineName.NormalizedText, MethodAttributes.Static);
            scope.MethodBuilders.Add(this.SubroutineName.NormalizedText, methodBuilder);
            CodeGenScope scope2 = new CodeGenScope
            {
                ILGenerator = methodBuilder.GetILGenerator(),
                TypeBuilder = scope.TypeBuilder,
                MethodBuilder = methodBuilder,
                Parent = scope
            };
            foreach (Statement current in this.SubroutineBody)
            {
                current.PrepareForEmit(scope2);
            }
        }
        public override void EmitIL(CodeGenScope scope)
        {
            MethodBuilder methodBuilder = scope.MethodBuilders[this.SubroutineName.NormalizedText];
            CodeGenScope codeGenScope = new CodeGenScope
            {
                ILGenerator = methodBuilder.GetILGenerator(),
                TypeBuilder = scope.TypeBuilder,
                MethodBuilder = methodBuilder,
                Parent = scope
            };
            foreach (Statement current in this.SubroutineBody)
            {
                current.EmitIL(codeGenScope);
            }
            codeGenScope.ILGenerator.Emit(OpCodes.Ret);
        }
        public override void PopulateCompletionItems(CompletionBag completionBag, int line, int column, bool globalScope)
        {
            if (base.StartToken.Line == line)
            {
                if (this.SubroutineName.Token == Token.Illegal || column < this.SubroutineName.Column)
                {
                    CompletionHelper.FillAllGlobalItems(completionBag, globalScope);
                    return;
                }
            }
            else
            {
                Statement statementContaining = Statement.GetStatementContaining(this.SubroutineBody, line);
                if (statementContaining != null)
                {
                    CompletionHelper.FillKeywords(completionBag, new Token[]
					{
						Token.EndSub
					});
                    statementContaining.PopulateCompletionItems(completionBag, line, column, false);
                }
            }
        }
        public override int GetIndentationLevel(int line)
        {
            if (line == this.SubToken.Line)
            {
                return 0;
            }
            if (this.EndSubToken.Token != Token.Illegal && line == this.EndSubToken.Line)
            {
                return 0;
            }
            Statement statementContaining = Statement.GetStatementContaining(this.SubroutineBody, line);
            if (statementContaining != null)
            {
                return 1 + statementContaining.GetIndentationLevel(line);
            }
            return 1;
        }
        public override string ToString()
        {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.AppendFormat(CultureInfo.CurrentUICulture, "{0} {1}\r\n", new object[]
			{
				this.SubToken.Text, 
				this.SubroutineName.Text
			});
            foreach (Statement current in this.SubroutineBody)
            {
                stringBuilder.AppendFormat(CultureInfo.CurrentUICulture, "  {0}", new object[]
				{
					current
				});
            }
            stringBuilder.AppendFormat(CultureInfo.CurrentUICulture, "{0}\r\n", new object[]
			{
				this.EndSubToken.Text
			});
            return stringBuilder.ToString();
        }
    }
}
